<script lang="ts" setup>
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
import type { Ref } from 'vue'
import { NCard, NRow, NCol, NStatistic } from 'naive-ui'
import { init } from 'echarts'
import type { ECharts } from 'echarts'
import http from '@/tools/http'
import { getTime } from '@/tools/date'
import { useConfigStore } from '@/stores/configStore'

const configStore = useConfigStore()

type ServerInfo = {
    hostName: string
    osName: string
    physicalProcessorCount: number
    systemWorkDuration: number
    totalDisk: number
    totalJvmMemory: number
    totalMemory: number
    totalSwap: number
    usedSwap: number
    availableMemory: number
    freeJvmMemory: number
    availableDisk: number
}

const serverInfo = reactive<ServerInfo>({
    hostName: "",
    osName: "",
    physicalProcessorCount: 0,
    systemWorkDuration: 0,
    totalDisk: 0,
    totalJvmMemory: 0,
    totalMemory: 0,
    totalSwap: 0,
    usedSwap: 0,
    availableMemory: 0,
    freeJvmMemory: 0,
    availableDisk: 0,
})

const workDateTime = computed(() => {
    const second = Math.floor(serverInfo.systemWorkDuration / 1000 % 60)
    const minute = Math.floor(serverInfo.systemWorkDuration / 1000 / 60 % 60)
    const hour = Math.floor(serverInfo.systemWorkDuration / 1000 / 60 / 60 % 24)
    const day = Math.floor(serverInfo.systemWorkDuration / 1000 / 60 / 60 / 24)
    return `${day}天${hour}时${minute}分${second}秒`
})

let workDateTimeTimer: any = undefined
let monitorTimer: any = undefined

let cpu: ECharts;
let memory: ECharts;
let disk: ECharts;
let jvm: ECharts;
const cpuRef: Ref<HTMLElement | null> = ref(null)
const memoryRef: Ref<HTMLElement | null> = ref(null)
const diskRef: Ref<HTMLElement | null> = ref(null)
const jvmRef: Ref<HTMLElement | null> = ref(null)
const optionTemplete: any = {
    title: {
        text: ""
    },
    tooltip: {
        trigger: "axis",

        formatter: '时间：{b}<br/>使用率：{c}%'
    },
    xAxis: {
        type: 'category',
        data: []
    },
    yAxis: {
        type: 'value',
        axisLabel: {
            formatter: '{value}%'
        }
    },
    series: [
        {
            data: [],
            type: 'line',
            itemStyle: {
                color: configStore.themeColor
            },
            lineStyle: {
                color: configStore.themeColor
            },
            areaStyle: {
                color: configStore.themeColor,
                opacity: 0.5
            }
        }
    ]
};
const chartTime: string[] = []
const cpuData: string[] = []
const memoryData: string[] = []
const diskData: string[] = []
const jvmData: string[] = []

onMounted(() => {
    monitor()
    initChart()
    getServerInfo()
})

onUnmounted(() => {
    closeChart()
    clearInterval(workDateTimeTimer)
    clearInterval(monitorTimer)
})

function initChart() {
    cpu = init(cpuRef.value as HTMLElement)
    memory = init(memoryRef.value as HTMLElement)
    jvm = init(jvmRef.value as HTMLElement)
    disk = init(diskRef.value as HTMLElement)
    cpu.setOption(optionTemplete)
    memory.setOption(optionTemplete)
    jvm.setOption(optionTemplete)
    disk.setOption(optionTemplete)
    window.addEventListener("resize", chartResize)
    monitorTimer = setInterval(() => {
        monitor()
    }, 3000)
}

function closeChart() {
    cpu.dispose()
    memory.dispose()
    jvm.dispose()
    disk.dispose()
    window.removeEventListener("resize", chartResize)
}

function chartResize() {
    cpu.resize()
    memory.resize()
    jvm.resize()
    disk.resize()
}

function getServerInfo() {
    http.post("/system/monitor/server").then(({ data }) => {
        if (data.code === "0") {
            serverInfo.hostName = data.data.hostName
            serverInfo.osName = data.data.osName
            serverInfo.physicalProcessorCount = data.data.physicalProcessorCount
            serverInfo.systemWorkDuration = data.data.systemWorkDuration
            serverInfo.totalDisk = data.data.totalDisk
            serverInfo.totalJvmMemory = data.data.totalJvmMemory
            serverInfo.totalMemory = data.data.totalMemory
            serverInfo.totalSwap = data.data.totalSwap
            clearInterval(workDateTimeTimer)
            workDateTimeTimer = setInterval(() => {
                serverInfo.systemWorkDuration += 1000
            }, 1000)
        }
    })
}

function monitor() {
    http.post("/system/monitor").then(({ data }) => {
        if (data.code === "0") {
            serverInfo.availableDisk = data.data.availableDisk
            serverInfo.usedSwap = data.data.usedSwap
            serverInfo.availableMemory = data.data.availableMemory
            serverInfo.freeJvmMemory = data.data.freeJvmMemory

            optionTemplete.series[0].itemStyle.color = configStore.themeColor
            optionTemplete.series[0].lineStyle.color = configStore.themeColor
            optionTemplete.series[0].areaStyle.color = configStore.themeColor
            chartTime.push(getTime())
            if (chartTime.length == 11) {
                chartTime.shift()
            }
            optionTemplete.xAxis.data = chartTime

            cpuData.push((data.data.usedCpu / data.data.totalCpu * 100).toFixed(1))
            if (cpuData.length == 11) {
                cpuData.shift()
            }
            optionTemplete.title.text = "CPU使用率"
            optionTemplete.series[0].data = cpuData
            cpu.setOption(optionTemplete)

            memoryData.push(((serverInfo.totalMemory - data.data.availableMemory) / serverInfo.totalMemory * 100).toFixed(1))
            if (memoryData.length == 11) {
                memoryData.shift()
            }
            optionTemplete.title.text = "内存使用率"
            optionTemplete.series[0].data = memoryData
            memory.setOption(optionTemplete)

            diskData.push(((serverInfo.totalDisk - data.data.availableDisk) / serverInfo.totalDisk * 100).toFixed(1))
            if (diskData.length == 11) {
                diskData.shift()
            }
            optionTemplete.title.text = "磁盘空间使用率"
            optionTemplete.series[0].data = diskData
            disk.setOption(optionTemplete)

            jvmData.push(((serverInfo.totalJvmMemory - data.data.freeJvmMemory) / serverInfo.totalJvmMemory * 100).toFixed(1))
            if (jvmData.length == 11) {
                jvmData.shift()
            }
            optionTemplete.title.text = "JVM内存使用率"
            optionTemplete.series[0].data = jvmData
            jvm.setOption(optionTemplete)
        }
    })
}
</script>
<template>
    <div class="flame-container">
        <n-card :content-style="{ overflowY: 'auto' }">
            <n-row>
                <n-col :span="6">
                    <n-statistic label="主机名称">
                        {{ serverInfo.hostName }}
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="操作系统">
                        {{ serverInfo.osName }}
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="CPU核数">
                        {{ serverInfo.physicalProcessorCount }}
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="运行时长">
                        {{ workDateTime }}
                    </n-statistic>
                </n-col>
            </n-row>
            <n-row style="margin-top:12px;">
                <n-col :span="6">
                    <n-statistic label="内存大小">
                        {{ ((serverInfo.totalMemory - serverInfo.availableMemory) / 1024 / 1024 / 1024).toFixed(2) }} GB
                        <template #suffix>
                            / {{ (serverInfo.totalMemory / 1024 / 1024 / 1024).toFixed(2) }} GB
                        </template>
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="磁盘大小">
                        {{ ((serverInfo.totalDisk - serverInfo.availableDisk) / 1024 / 1024 / 1024).toFixed(2) }} GB
                        <template #suffix>
                            / {{ (serverInfo.totalDisk / 1024 / 1024 / 1024).toFixed(2) }} GB
                        </template>
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="交换区大小">
                        {{ (serverInfo.usedSwap / 1024 / 1024 / 1024).toFixed(2) }} GB
                        <template #suffix>
                            / {{ (serverInfo.totalSwap / 1024 / 1024 / 1024).toFixed(2) }} GB
                        </template>
                    </n-statistic>
                </n-col>
                <n-col :span="6">
                    <n-statistic label="JVM内存大小">
                        {{ ((serverInfo.totalJvmMemory - serverInfo.freeJvmMemory) / 1024 / 1024).toFixed(2) }} MB
                        <template #suffix>
                            / {{ (serverInfo.totalJvmMemory / 1024 / 1024).toFixed(2) }} MB
                        </template>
                    </n-statistic>
                </n-col>
            </n-row>
            <div style="display:flex;margin-top:24px;">
                <div ref="cpuRef" id="cpu" style="width: 50%;height:300px;"></div>
                <div ref="memoryRef" id="memory" style="width: 50%;height:300px;"></div>
            </div>
            <div style="display:flex;">
                <div ref="diskRef" id="disk" style="width: 50%;height:300px;"></div>
                <div ref="jvmRef" id="jvm" style="width: 50%;height:300px;"></div>
            </div>
        </n-card>
    </div>
</template>
<style scoped></style>